home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / IBMPC / MS_MISC.C < prev    next >
C/C++ Source or Header  |  1992-12-08  |  11KB  |  512 lines

  1. /* ibmpc/ms_misc.c: MSDOS support code
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Don Kneller
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #ifdef __TURBOC__
  10. #include    <conio.h>
  11. #endif /* __TURBOC__ */
  12.  
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include <time.h>
  16. #include <fcntl.h>
  17. #include <stdio.h>
  18.  
  19. #include "config.h"
  20. #include "constant.h"
  21. #include "types.h"
  22. #include "externs.h"
  23.  
  24. #ifdef MSDOS
  25. #ifndef USING_TCIO
  26. /* We don't want to include curses.h when using the tcio.c file.  */
  27. #include <curses.h>
  28. #endif
  29. #ifdef ANSI
  30. #include "ms_ansi.h"
  31. #endif
  32.  
  33. #ifdef LINT_ARGS
  34. void exit(int);
  35. static FILE *fopenp(char *, char *, char *);
  36. static    unsigned int ioctl(int ,int ,unsigned int );
  37. #else
  38. void exit();
  39. static unsigned int ioctl();
  40. #endif
  41.  
  42. extern char *getenv();
  43.  
  44. #define PATHLEN    80
  45. char    moriatop[PATHLEN];
  46. char    moriasav[PATHLEN];
  47. int    saveprompt = TRUE;
  48. int    ibmbios;
  49. static    int    rawio;
  50. int8u    floorsym = '.';
  51. int8u    wallsym = '#';
  52.  
  53. /* UNIX compatability routines */
  54. void user_name(buf)
  55. char *buf;
  56. {
  57.   strcpy(buf, getlogin());
  58. }
  59.  
  60. char    *
  61. getlogin()
  62. {
  63.     char    *cp;
  64.  
  65.     if ((cp = getenv("USER")) == NULL)
  66.         cp = "player";
  67.     return cp;
  68. }
  69.  
  70. #ifndef __TURBOC__
  71. unsigned int
  72. sleep(secs)
  73. int    secs;
  74. {
  75.     time_t    finish_time;
  76.  
  77.     finish_time = time((long *) NULL) + secs;
  78.     while (time((long *) NULL) < finish_time)
  79.         /* nothing */;
  80.     return 0;
  81. }
  82. #endif
  83.  
  84. #ifdef OLD
  85. /* This is the old code.  It is not strictly correct; it is retained in
  86.    case the correct code below is not portable.  You will also have to
  87.    change the declarations for these functions in externs.h.  */
  88. void
  89. error(fmt, a1, a2, a3, a4)
  90. char    *fmt;
  91. int    a1, a2, a3, a4;
  92. {
  93.     fprintf(stderr, "MORIA error: ");
  94.     fprintf(stderr, fmt, a1, a2, a3, a4);
  95.     (void) sleep(2);
  96.     exit(1);
  97. }
  98.  
  99. void
  100. warn(fmt, a1, a2, a3, a4)
  101. char    *fmt;
  102. int    a1, a2, a3, a4;
  103. {
  104.     fprintf(stderr, "MORIA warning: ");
  105.     fprintf(stderr, fmt, a1, a2, a3, a4);
  106.     (void) sleep(2);
  107. }
  108. #else
  109.  
  110. #include <stdarg.h>
  111.  
  112. void
  113. error (char *fmt, ...)
  114. {
  115.   va_list p_arg;
  116.  
  117.   va_start (p_arg, fmt);
  118.   fprintf (stderr, "Moria error: ");
  119.   vfprintf (stderr, fmt, p_arg);
  120.   sleep (2);
  121.   exit (1);
  122. }
  123.  
  124. void
  125. warn(char *fmt, ...)
  126. {
  127.   va_list p_arg;
  128.  
  129.   va_start(p_arg, fmt);
  130.   fprintf(stderr, "MORIA warning: ");
  131.   vfprintf(stderr, fmt, p_arg);
  132.   sleep(2);
  133. }
  134. #endif
  135.  
  136. /* Search the path for a file of name "name".  The directory is
  137.  * filled in with the directory part of the path.
  138.  */
  139. static FILE *
  140. fopenp(name, mode, directory)
  141. char *name, *mode, directory[];
  142. {
  143.     char *dp, *pathp, *getenv(), lastch;
  144.     FILE *fp;
  145.  
  146.     /* Try the default directory first.  If the file can't be opened,
  147.      * start looking along the path.
  148.      */
  149.     fp = fopen (name, mode);
  150.     if (fp) {
  151.         directory[0] = '\0';
  152.         return fp;
  153.     }
  154.     pathp = getenv("PATH");
  155.     while (pathp && *pathp) {
  156.         dp = directory;
  157.         while (*pathp && *pathp != ';')
  158.             lastch = *dp++ = *pathp++;
  159.         if (lastch != '\\' && lastch != '/' && lastch != ':')
  160.             *dp++ = '\\';
  161.         (void) strcpy(dp, name);
  162.         fp = fopen (directory, mode);
  163.         if (fp) {
  164.             *dp = '\0';
  165.             return fp;
  166.         }
  167.         if (*pathp)
  168.             pathp++;
  169.     }
  170.     directory[0] = '\0';
  171.     return NULL;
  172. }
  173.  
  174. /* Read the configuration.
  175.  */
  176. void
  177. msdos_init()
  178. {
  179.     char    buf[BUFSIZ], *bp, opt[PATHLEN];
  180.     int    arg1, arg2, cnt;
  181.     FILE    *fp;
  182.  
  183.     buf[0] = '\0';
  184.     bp = MORIA_CNF_NAME;
  185.     fp = fopenp(bp, "r", buf);
  186.     (void) strcpy(moriatop, buf);
  187.     (void) strcat(moriatop, MORIA_TOP_NAME);
  188.     (void) strcpy(moriasav, buf);
  189.     (void) strcat(moriasav, MORIA_SAV_NAME);
  190.     if (fp == NULL) {
  191.         warn("Can't find configuration file `%s'\n", bp);
  192.         return;
  193.     }
  194.     printf("Reading configuration from %s%s\n", buf, bp);
  195.     (void) sleep(1);
  196.     while (fgets(buf, sizeof buf, fp)) {
  197.         if (*buf == '#')
  198.             continue;
  199.  
  200.         cnt = sscanf(buf, "%s", opt);
  201.         /* Turbo C will return EOF when reading an empty line,
  202.            MSC will correctly read a NULL character */
  203.         if (cnt == 0 ||
  204. #ifdef __TURBOC__
  205.             cnt == EOF ||
  206. #endif
  207.             opt[0] == '\0')
  208.             continue;
  209.  
  210.         /* Go through possible variables
  211.          */
  212.         if (strcmpi(opt, "GRAPHICS") == 0) {
  213.             cnt = sscanf(buf, "%*s%d %d\n", &arg1, &arg2);
  214.             if (cnt != 2)
  215.                 warn("GRAPHICS did not contain 2 values\n");
  216.             else {
  217.                 wallsym = (int8u) arg1;
  218.                 floorsym = (int8u) arg2;
  219.  
  220.                 /* Adjust lists that depend on '#' and '.' */
  221.                 object_list[OBJ_SECRET_DOOR].tchar = wallsym;
  222.             }
  223.         }
  224.         else if (strcmpi(opt, "SAVE") == 0) {
  225.             cnt = sscanf(buf, "%*s%s", opt);
  226.             if (cnt == 0)
  227.                 warn("SAVE option requires a filename\n");
  228.             else {
  229.                     bp = strchr (opt, ';');
  230.                 if (bp) {
  231.                     *bp++ = '\0';
  232.                     if (*bp == 'n' || *bp == 'N')
  233.                         saveprompt = FALSE;
  234.                 }
  235.                 if (opt[0])
  236.                     (void) strcpy(moriasav, opt);
  237.             }
  238.         }
  239.         else if (strcmpi(opt, "SCORE") == 0) {
  240.             cnt = sscanf(buf, "%*s%s", opt);
  241.             if (cnt == 0)
  242.                 warn("SCORE option requires a filename\n");
  243.             else
  244.                 (void) strcpy(moriatop, opt);
  245.         }
  246.         else if (strcmpi(opt, "KEYBOARD") == 0) {
  247.             cnt = sscanf(buf, "%*s%s", opt);
  248.             if (cnt == 0)
  249.                 warn("KEYBOARD option requires a value\n");
  250.             else if (strcmpi(opt, "ROGUE") == 0)
  251.                 rogue_like_commands = TRUE;
  252.             else if (strcmpi(opt, "VMS") == 0)
  253.                 rogue_like_commands = FALSE;
  254.         }
  255.         else if (strcmpi(opt, "IBMBIOS") == 0)
  256.             ibmbios = TRUE;
  257.         else if (strcmpi(opt, "RAWIO") == 0)
  258.             rawio = TRUE;
  259. #ifdef ANSI
  260.         /* Usage: ANSI [ check_ansi [ domoveopt [ tgoto ] ] ]
  261.          * where check_ansi and domoveopt are "Y"es unless explicitly
  262.          * set to "N"o.     Tgoto is "N"o unless set to "Y"es.
  263.          */
  264.         else if (strcmpi(opt, "ANSI") == 0) {
  265.             cnt=sscanf(buf, "%*s%1s%1s%1s",&opt[0],&opt[1],&opt[2]);
  266.             ansi_prep(cnt < 1 || opt[0] == 'y' || opt[0] == 'Y',
  267.                  cnt < 2 || opt[1] == 'y' || opt[1] == 'Y',
  268.                  cnt >= 3 && (opt[2] == 'y' || opt[2] == 'Y'));
  269.         }
  270. #endif
  271.         else
  272.             warn("Unknown configuration line: `%s'\n", buf);
  273.     }
  274.     fclose(fp);
  275.  
  276.     /* The only text file has been read.  Switch to binary mode */
  277. }
  278.  
  279. #include <dos.h>
  280. #define DEVICE    0x80
  281. #define RAW    0x20
  282. #define IOCTL    0x44
  283. #define STDIN    fileno(stdin)
  284. #define STDOUT    fileno(stdout)
  285. #define GETBITS    0
  286. #define SETBITS    1
  287.  
  288. static unsigned    old_stdin, old_stdout, ioctl();
  289.  
  290. void
  291. msdos_raw() {
  292.     if (!rawio)
  293.         return;
  294.     old_stdin = ioctl(STDIN, GETBITS, 0);
  295.     old_stdout = ioctl(STDOUT, GETBITS, 0);
  296.     if (old_stdin & DEVICE)
  297.         ioctl(STDIN, SETBITS, old_stdin | RAW);
  298.     if (old_stdout & DEVICE)
  299.         ioctl(STDOUT, SETBITS, old_stdout | RAW);
  300. }
  301.  
  302. void
  303. msdos_noraw() {
  304.     if (!rawio)
  305.         return;
  306.     if (old_stdin)
  307.         (void) ioctl(STDIN, SETBITS, old_stdin);
  308.     if (old_stdout)
  309.         (void) ioctl(STDOUT, SETBITS, old_stdout);
  310. }
  311.  
  312. static unsigned int
  313. ioctl(handle, mode, setvalue)
  314. unsigned int setvalue;
  315. {
  316.     union REGS regs;
  317.  
  318.     regs.h.ah = IOCTL;
  319.     regs.h.al = (unsigned char) mode;
  320.     regs.x.bx = handle;
  321.     regs.h.dl = (unsigned char) setvalue;
  322.     regs.h.dh = 0;            /* Zero out dh */
  323.     intdos(®s, ®s);
  324.     return (regs.x.dx);
  325. }
  326.  
  327. /* Normal characters are output when the shift key is not pushed.
  328.  * Shift characters are output when either shift key is pushed.
  329.  */
  330. #define KEYPADHI    83
  331. #define KEYPADLOW    71
  332. #define ISKEYPAD(x)    (KEYPADLOW <= (x) && (x) <= KEYPADHI)
  333. #undef CTRL
  334. #define CTRL(x)        (x - '@')
  335. typedef struct {
  336.     char normal, shift, numlock;
  337. } KEY;
  338. static KEY roguekeypad[KEYPADHI - KEYPADLOW + 1] = {
  339.     {'y', 'Y', CTRL('Y')},            /* 7 */
  340.     {'k', 'K', CTRL('K')},            /* 8 */
  341.     {'u', 'U', CTRL('U')},            /* 9 */
  342.     {'.', '.', '.'},            /* - */
  343.     {'h', 'H', CTRL('H')},            /* 4 */
  344.     {'.', '.', '.'},            /* 5 */
  345.     {'l', 'L', CTRL('L')},            /* 6 */
  346.     {CTRL('P'), CTRL('P'), CTRL('P')},    /* + */
  347.     {'b', 'B', CTRL('B')},            /* 1 */
  348.     {'j', 'J', CTRL('J')},            /* 2 */
  349.     {'n', 'N', CTRL('N')},            /* 3 */
  350.     {'i', 'i', 'i'},            /* Ins */
  351.     {'.', '.', '.'}                /* Del */
  352. };
  353. static KEY originalkeypad[KEYPADHI - KEYPADLOW + 1] = {
  354.     {'7', '7', '7'},            /* 7 */
  355.     {'8', '8', '8'},            /* 8 */
  356.     {'9', '9', '9'},            /* 9 */
  357.     {'-', '-', '-'},            /* - */
  358.     {'4', '4', '4'},            /* 4 */
  359.     {'5', '5', '5'},            /* 5  - move */
  360.     {'6', '6', '6'},            /* 6 */
  361.     {CTRL('M'), CTRL('M'), CTRL('M')},    /* + */
  362.     {'1', '1', '1'},            /* 1 */
  363.     {'2', '2', '2'},            /* 2 */
  364.     {'3', '3', '3'},            /* 3 */
  365.     {'i', 'i', 'i'},        /* Ins */
  366.     {'.', '.', '.'}            /* Del */
  367. };
  368.  
  369. /* bios_getch gets keys directly with a BIOS call.
  370.  */
  371. #define SHIFT        (0x1 | 0x2)
  372. #define NUMLOCK        0x20
  373. #define KEYBRD_BIOS    0x16
  374.  
  375. int
  376. bios_getch()
  377. {
  378.     unsigned char scan, shift;
  379.     int    ch;
  380.     KEY    *kp;
  381.     union REGS regs;
  382.  
  383.     if (rogue_like_commands)
  384.         kp = roguekeypad;
  385.     else
  386.         kp = originalkeypad;
  387.  
  388.     /* Get scan code.
  389.      */
  390.     regs.h.ah = 0;
  391.     int86(KEYBRD_BIOS, ®s, ®s);
  392.     ch = regs.h.al;
  393.     scan = regs.h.ah;
  394.  
  395.     /* Get shift status.
  396.      */
  397.     regs.h.ah = 2;
  398.     int86(KEYBRD_BIOS, ®s, ®s);
  399.     shift = regs.h.al;
  400.  
  401.     /* If scan code is for the keypad, translate it.
  402.      */
  403.     if (ISKEYPAD(scan)) {
  404.         if (shift & NUMLOCK)
  405.             ch = kp[scan - KEYPADLOW].numlock;
  406.         else if (shift & SHIFT)
  407.             ch = kp[scan - KEYPADLOW].shift;
  408.         else
  409.             ch = kp[scan - KEYPADLOW].normal;
  410.     }
  411.     return ch;
  412. }
  413.  
  414. int
  415. msdos_getch()
  416. {
  417.     int    ch;
  418.  
  419.     if (ibmbios)
  420.         ch = bios_getch();
  421.     else {
  422.         ch = getch();
  423.         if (ch == 0)
  424.             ch = getch();
  425.     }
  426.     return ch;
  427. }
  428.  
  429. #if 0
  430. /* This intro message deleted because it is obsolete.  */
  431.  
  432. /* Hardcode the introductory message in */
  433. void
  434. msdos_intro()
  435. {
  436.         char buf[80];
  437.  
  438.     clear_screen();
  439.         wmove(stdscr,0,0);
  440.     waddstr(stdscr,"                         *********************");
  441.     wmove(stdscr,1,0);
  442.         sprintf(buf,"                         **   Moria %d.%d    **",
  443.       CUR_VERSION_MAJ, CUR_VERSION_MIN);
  444.         waddstr(stdscr,buf);
  445.         wmove(stdscr,2,0);
  446.     waddstr(stdscr,"                         *********************");
  447.         wmove(stdscr,3,0);
  448.     waddstr(stdscr,"                   COPYRIGHT (c) Robert Alan Koeneke");
  449.         wmove(stdscr,5,0);
  450.     waddstr(stdscr,"Programmers : Robert Alan Koeneke / University of Oklahoma");
  451.         wmove(stdscr,6,0);
  452.     waddstr(stdscr,"              Jimmey Wayne Todd   / University of Oklahoma");
  453.         wmove(stdscr,8,0);
  454.     waddstr(stdscr,"UNIX Port   : James E. Wilson     / Cygnus Support");
  455.         wmove(stdscr,10,0);
  456.     waddstr(stdscr,"MSDOS Port  : Don Kneller         / 1349 - 10th ave");
  457.         wmove(stdscr,11,0);
  458.     waddstr(stdscr,
  459.         "                                  / San Francisco, CA 94122");
  460.         wmove(stdscr,12,0);
  461.     waddstr(stdscr,"                                  / Dec 12, 1988");
  462.     pause_line(23);
  463. }
  464. #endif
  465.  
  466. #ifdef PC_CURSES
  467. /* Seems to be a bug in PCcurses whereby it won't really clear the screen
  468.  * if there are characters there it doesn't know about.
  469.  */
  470. #define VIDEOINT    0x10
  471. void
  472. bios_clear()
  473. {
  474.     union REGS regs;
  475.     unsigned char    nocols, activepage;
  476.  
  477. #ifdef ANSI
  478.     if (ansi)
  479.         return;
  480. #endif
  481.  
  482.     /* get video attributes */
  483.     regs.h.ah = 15;
  484.     int86(VIDEOINT, ®s, ®s);
  485.     nocols = regs.h.ah;
  486.     activepage = regs.h.bh;
  487.  
  488.     /* Move to lower right corner */
  489.     regs.h.ah = 2;
  490.     regs.h.dh = (unsigned char) 24;
  491.     regs.h.dl = nocols - 1;    /* lower right col */
  492.     regs.h.bh = activepage;
  493.     int86(VIDEOINT, ®s, ®s);
  494.  
  495.     /* get current attribute into bh */
  496.     regs.h.ah = 8;
  497.     regs.h.bh = activepage;
  498.     int86(VIDEOINT, ®s, ®s);
  499.     regs.h.bh = regs.h.ah;
  500.  
  501.     regs.h.cl = 0;    /* upper left row */
  502.     regs.h.ch = 0;    /* upper left col */
  503.     regs.h.dh = (unsigned char) 24;    /* lower right row */
  504.     regs.h.dl = nocols - 1;    /* lower right col */
  505.     regs.h.al = 0;    /* clear window */
  506.     regs.h.ah = 7;    /* scroll down */
  507.     int86(VIDEOINT, ®s, ®s);
  508. }
  509. #endif
  510.  
  511. #endif
  512.